﻿using FluentAssertions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using NewRetail.Application.Components.WeChat.CardVoucher.Model;
using NewRetail.Application.Components.WeChat.Member.Model;
using NewRetail.Application.Components.WeChat.Member.Services;
using NewRetail.Application.Components.WeChat.Model.ResponseEvent;
using NewRetail.Application.Components.WeChat.Model.ResponseMessage;
using NewRetail.Application.Utility;
using SKIT.FlurlHttpClient.Wechat.Api;
using SKIT.FlurlHttpClient.Wechat.Api.Events;
using NewRetail.Application.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using NewRetail.Application.Components.WeChat.Configurations;
using NewRetail.Application.Components.WeChat.Model;
using Microsoft.Extensions.Options;
using SKIT.FlurlHttpClient.Wechat.TenpayV3;
using NewRetail.Application.Components.WeChat.CardVoucher.Services;
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Events;

namespace NewRetail.Application.Components.WeChat.Services
{
    /// <summary>
    /// 响应微信回复的接口
    /// </summary>
    public interface IReplySetService : IApplicationService
    {
        /// <summary>
        /// event事件回调
        /// </summary>
        /// <param name="xmlContent"></param>
        /// <param name="wechatApiClient"></param>
        /// <param name="appId"></param>
        /// <returns></returns>
        Task<string> OnEventRequest(string xmlContent, WechatApiClient wechatApiClient, string appId);
        /// <summary>
        /// event事件回调
        /// </summary>
        /// <param name="xmlContent"></param>
        /// <returns></returns>
        Task<string> OnEventRequest(string xmlContent);
        /// <summary>
        /// text事件回调
        /// </summary>
        /// <param name="xmlContent"></param>
        /// <returns></returns>
        Task<string> OnTextRequest(string xmlContent);
        /// <summary>
        /// 核销事件回调
        /// </summary>
        /// <param name="jsonContent"></param>
        /// <param name="wechatTenpayClient"></param>
        /// <param name="merchantId"></param>
        /// <returns></returns>
        Task<string> OnWriteOffEventRequest(string jsonContent, WechatTenpayClient wechatTenpayClient, string merchantId);
    }

    /// <summary>
    /// 响应微信回复的实现
    /// </summary>
    public class ReplySetService : ApplicationService, IReplySetService
    {
        #region Field
        private readonly IMemberService _memberServices;
        private readonly IConfiguration _configuration;
        private readonly ILogger _logger;
        private readonly RedisClient _redisClient;
        private readonly StackExchange.Redis.IDatabase _redis;
        private readonly WeChatOptions _wechatOptions;
        public readonly ICardVoucherService _cardVoucherService;
        #endregion

        #region 构造函数
        public ReplySetService(IMemberService memberServices, IConfiguration configuration, ILogger<ReplySetService> logger, RedisClient redisClient,
            IOptions<WeChatOptions> wechatOptions, ICardVoucherService cardVoucherService)
        {
            _memberServices = memberServices;
            _configuration = configuration;
            _logger = logger;
            _wechatOptions = wechatOptions.Value;
            _redisClient = redisClient;
            _redis = _redisClient.Connection.GetDatabase(2);
            _cardVoucherService = cardVoucherService;
        }
        #endregion

        #region Implementation of ISignatureService

        #region event事件回调
        /// <summary>
        /// event事件回调
        /// </summary>
        /// <param name="xmlContent"></param>
        /// <param name="wechatApiClient"></param>
        /// <param name="appId"></param>
        /// <returns></returns>
        public async Task<string> OnEventRequest(string xmlContent, WechatApiClient wechatApiClient, string appId)
        {
            var result = "";
            //获取事件类型
            var eventType = EventTypeConvert.GetEventTypeByString(wechatApiClient.DeserializeEventFromXml(xmlContent).Event);
            var openId = "";
            var inputData = new CardMemberUserInfoInputDto();
            var defaultMemberTypeID = _configuration["default_member_type_id"];
            defaultMemberTypeID.Should().NotBeNullOrEmpty();
            _logger.LogInformation("微信反馈的会员信息:" + xmlContent);
            switch (eventType)
            {
                case EventType.Scan:
                    //将xml内容转成对象,扫码关注（已关注情况）
                    var scanPushMsg = wechatApiClient.DeserializeEventFromXml<ScanPushEvent>(xmlContent);
                    openId = scanPushMsg.FromUserName;
                    //根据获取的openId校验会员是否存在，不存在则加入
                    var weChatMemberScanPush = new WeChatMemberVerAdd()
                    {
                        openId = openId,
                        sourceWarehouseID = scanPushMsg.EventKey,
                        appId = appId,
                        memberTypeID = defaultMemberTypeID
                    };
                    await _memberServices.VerifyMemberAdd(weChatMemberScanPush, "GZ");
                    //关注发送消息
                    result = await GetGzAccountResponse(appId, scanPushMsg.ToUserName, openId, scanPushMsg.CreateTimestamp);
                    ////关注发送欢迎等模板消息
                    //await _memberServices.SendTemplateMessageByType(appId, openId, 0);
                    break;
                case EventType.Subscribe:
                    //将xml内容转成对象,扫码关注（未关注情况）
                    var subscribePushMsg = wechatApiClient.DeserializeEventFromXml<SubscribePushEvent>(xmlContent);
                    var eventKey = subscribePushMsg.EventKey;
                    openId = subscribePushMsg.FromUserName;
                    var weChatMemberSubscribePush = new WeChatMemberVerAdd()
                    {
                        openId = openId,
                        sourceWarehouseID = !string.IsNullOrEmpty(eventKey) ? eventKey.Substring(eventKey.IndexOf("qrscene_") + "qrscene_".Length) : "",
                        appId = appId,
                        memberTypeID = defaultMemberTypeID
                    };
                    //如果eventKey为空，则是分享或查找公众号或其他途径关注的，则没有来源门店Id
                    //根据获取的openId校验会员是否存在，不存在则加入,因为取消关注后重新关注还会走这边
                    await _memberServices.VerifyMemberAdd(weChatMemberSubscribePush, "GZ");
                    //关注发送消息
                    result = await GetGzAccountResponse(appId, subscribePushMsg.ToUserName, openId, subscribePushMsg.CreateTimestamp);

                    ////如果eventKey为空，则是分享或查找公众号关注的
                    //if (!string.IsNullOrEmpty(eventKey))
                    //{
                    //    //根据获取的openId校验会员是否存在，不存在则加入,因为取消关注后重新关注还会走这边
                    //    await _memberServices.VerifyMemberAdd(weChatMemberSubscribePush, "GZ");
                    //    ////关注发送欢迎等模板消息
                    //    //await _memberServices.SendTemplateMessageByType(appId, openId, 0);
                    //}
                    //else
                    //{
                    //    //如果eventKey为空，则是分享或查找公众号或其他途径关注的，则没有来源门店Id

                    //    //根据获取的openId校验会员是否存在，不存在则加入,因为取消关注后重新关注还会走这边
                    //    await _memberServices.VerifyMemberAdd(weChatMemberSubscribePush, "GZ");
                    //}
                    break;
                case EventType.Card_User_Member_Submit:
                    //将xml内容转成对象.激活
                    var submitMemberCardUserInfo = wechatApiClient.DeserializeEventFromXml<SubmitMemberCardUserInfoEvent>(xmlContent);
                    inputData = new CardMemberUserInfoInputDto()
                    {
                        AppId = appId,
                        CardId = submitMemberCardUserInfo.CardId,
                        CardCode = submitMemberCardUserInfo.CardCode
                    };
                    GetCardMemberUserInfo(inputData, appId, defaultMemberTypeID);
                    break;
                case EventType.Card_User_Get:
                    //将xml内容转成对象
                    var userGetCard = wechatApiClient.DeserializeEventFromXml<UserGetCardEvent>(xmlContent);
                    inputData = new CardMemberUserInfoInputDto()
                    {
                        AppId = appId,
                        CardId = userGetCard.CardId,
                        CardCode = userGetCard.CardCode
                    };
                    GetCardMemberUserInfo(inputData, appId, defaultMemberTypeID);
                    break;
                default:
                    result = "";
                    break;
                    //throw new NotSupportedException("不支持的请求事件类型：" + eventType);
            }


            return result;
        }
        #endregion

        #region text事件回调
        /// <summary>
        /// text事件回调
        /// </summary>
        /// <param name="xmlContent"></param>
        /// <returns></returns>
        public async Task<string> OnTextRequest(string xmlContent)
        {
            var resXml = await GetKeyWord(xmlContent);

            return resXml;
        }
        #endregion        

        #region event事件回调(弃用)
        /// <summary>
        /// event事件回调
        /// </summary>
        /// <param name="xmlContent"></param>
        /// <returns></returns>
        public Task<string> OnEventRequest(string xmlContent)
        {
            //将xml内容转成对象
            var msgBase = XmlEntityExchange<EventConvertMessageBase>.ConvertXml2Entity(xmlContent);
            var eventType = EventTypeConvert.GetEventTypeByString(msgBase.Event);
            switch (eventType)
            {
                case EventType.Scan:
                    //将xml内容转成对象
                    var scanMsg = XmlEntityExchange<ScanQrCodePushMessage>.ConvertXml2Entity(xmlContent);
                    break;

                default:
                    throw new NotSupportedException("不支持的请求事件类型：" + msgBase.Event);
            }
            string resXml = "";

            return Task.FromResult(resXml);
        }
        #endregion

        #region 回调通知事件
        /// <summary>
        /// 回调通知事件
        /// </summary>
        /// <param name="jsonContent"></param>
        /// <param name="wechatTenpayClient"></param>
        /// <param name="merchantId"></param>
        /// <returns></returns>
        public async Task<string> OnWriteOffEventRequest(string jsonContent, WechatTenpayClient wechatTenpayClient, string merchantId)
        {
            var result = "";
            //获取事件类型
            var objContent = wechatTenpayClient.DeserializeEvent(jsonContent);
            var eventType = objContent.EventType;
            _logger.LogInformation("eventType:" + eventType);
            switch (eventType)
            {
                case "COUPON.USE":
                    //核销券通知
                    var retFlag = await _cardVoucherService.UpdataUserCoupons(objContent, merchantId);
                    break;
                case "TRANSACTION.SUCCESS":
                    //支付通知 根据事件类型，解密得到支付通知敏感数据
                    var callbackResource = wechatTenpayClient.DecryptEventResource<TransactionResource>(objContent);
                    string outTradeNumber = callbackResource.OutTradeNumber;
                    string transactionId = callbackResource.TransactionId;
                    _logger.LogInformation("payResult:" + Newtonsoft.Json.JsonConvert.SerializeObject(callbackResource, Newtonsoft.Json.Formatting.Indented));
                    break;
            }
            return result;
        }
        #endregion

    #endregion

        #region help类

        #region 获取帮助菜单文档
    /// <summary>
    /// 获取帮助菜单文档
    /// </summary>
    /// <returns></returns>
    private string HelpDocument()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("HI，请回复数字，选择服务").Append("\n\n");
            sb.Append("1. 当前时间").Append("\n");
            sb.Append("2. 天气信息").Append("\n");
            sb.Append("3. 聊天唠嗑").Append("\n");
            sb.Append("n. 更多服务开发中...").Append("\n");
            sb.Append("回复【?】显示此帮助菜单");
            return sb.ToString();
        }
        #endregion

        #region 关键字回复
        /// <summary>
        /// 关键字回复
        /// </summary>
        /// <param name="xmlContent"></param>
        /// <returns></returns>
        private Task<string> GetKeyWord(string xmlContent)
        {
            var resXml = "";
            //将xml内容转成对象
            var msg = XmlEntityExchange<ResponseMessageText>.ConvertXml2Entity(xmlContent);
            //返回消息，互换收发用户
            string toUser = msg.FromUserName;
            msg.FromUserName = msg.ToUserName;
            msg.ToUserName = toUser;
            //根据回复的关键字返回内容
            switch (msg.Content.Trim())
            {
                case "?":
                    msg.Content = HelpDocument();
                    break;
                case "？":
                    msg.Content = HelpDocument();
                    break;
                case "1":
                    msg.Content = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    break;
                case "2":
                    msg.Content = "获取天气正在维护";// Tools.HttpCrossDomain.Get("http://www.weather.com.cn/data/sk/101210301.html");
                    break;
                case "3":
                    msg.Content = "来吧，想唠点什么呢？ [偷笑]";
                    break;
                case "4":
                    msg.Content = "欢迎关注，请<a href='https://mp.weixin.qq.com/bizmall/activatemembercard?action=preshow&&encrypt_card_id=b0dKpA6h0EZbB%2BcvlSu2aALN1An%2FaLrLAGzCSZ2Gm538VHgM5dpWaxkL8AlSkKw%2B&outer_str=1ng&biz=MzkwNDIwNjY3NA%3D%3D#wechat_redirect'>注册会员</a>";
                    break;
                case "你是男的女的":
                    msg.Content = "姑娘一枚 [偷笑]";
                    break;
                case "id":
                    msg.Content = toUser;
                    break;
                default:
                    msg.Content = "抱歉哦，我不认识您输入的命令。/害羞 /:,@-D";
                    break;
            }
            //返回微信消息xml格式
            resXml = XmlEntityExchange<ResponseMessageText>.ConvertEntity2Xml(msg);
            return Task.FromResult(resXml);
        }
        #endregion 关键字回复

        #region 激活或获取会员卡回调时候获取手机号
        private void GetCardMemberUserInfo(CardMemberUserInfoInputDto inputData, string appId, string defaultMemberTypeID) 
        {
            var resultItem = _memberServices.GetCardMemberUserInfoAsync(inputData).Result;
            var cardMemberUserInfo = resultItem.Item1;
            if (cardMemberUserInfo != null)
            {
                _logger.LogInformation("会员信息:" + UtilsHelper.SerializeObject(cardMemberUserInfo));
                var openId = cardMemberUserInfo.OpenId;
                var memberName = cardMemberUserInfo.Nickname;
                var memberNo = cardMemberUserInfo.MembershipNumber;
                var memberTel = cardMemberUserInfo.MemberUser?.CommonFieldList.FirstOrDefault(x => x.Name == "USER_FORM_INFO_FLAG_MOBILE")?.Value;
                //生日
                var memberBirthday = cardMemberUserInfo.MemberUser?.CommonFieldList.FirstOrDefault(x => x.Name == "USER_FORM_INFO_FLAG_BIRTHDAY")?.Value;
                //将2022-2-3转换成yyyy-MM-dd
                if (!string.IsNullOrWhiteSpace(memberBirthday))
                {
                    memberBirthday = Convert.ToDateTime(memberBirthday).ToString("yyyy-MM-dd");
                }
                //0:女  1:男
                var memberSex = cardMemberUserInfo.Sex == "MALE" ? 1 : 0;
                var weChatMember = new WeChatMemberVerAdd()
                {
                    memberName = memberName,
                    openId = openId,
                    sourceWarehouseID = "",
                    appId = appId,
                    memberTypeID = defaultMemberTypeID,
                    memberTel = memberTel,
                    memberNo = memberNo,
                    memberSex = memberSex,
                    memberBirthday = memberBirthday
                };
                _logger.LogInformation($"会员详细信息【openId:{openId},memberNo:{memberNo},memberTel:{memberTel}】");
                var retMember = _memberServices.VerifyMemberAdd(weChatMember, "LKJH").GetAwaiter().GetResult();
                if(retMember == false)
                    _logger.LogError("回调拉取会员信息失败" + resultItem.Item2);
            }
            else
                _logger.LogError("回调拉取会员信息失败！" + resultItem.Item2);            
        }
        #endregion

        #region 关注公众号回复内容
        /// <summary>
        /// 关注公众号回复内容
        /// </summary>
        /// <param name="appId"></param>
        /// <param name="fromUserName"></param>
        /// <param name="toUserName"></param>
        /// <param name="createTimestamp"></param>
        /// <returns></returns>
        private async Task<string> GetGzAccountResponse(string appId, string fromUserName, string toUserName, long createTimestamp)
        {
            var resXml = "";
            var msgText = new ResponseMessageText()
            {
                MsgType = "text",
                FromUserName = fromUserName,
                ToUserName = toUserName,
                CreateTime = (ulong)createTimestamp
            };
            //检查是否已存在线上会员,不存在则需要发送会员卡激活，反之不需要激活
            var memberInfoFlag = await _memberServices.IsExistsMemberByOpenId(toUserName);
            if (!memberInfoFlag)
            {
                var memberCardId = _wechatOptions.Accounts?.FirstOrDefault(e => string.Equals(appId, e.AppId)).MemberCardId;
                if (!string.IsNullOrEmpty(memberCardId))
                {
                    var memberCardActiveInfo = await GetMemberCardActive(appId, memberCardId);
                    var jpUrl = memberCardActiveInfo?.JpUrl;
                    if(string.IsNullOrEmpty(jpUrl))
                    {
                        //没有跳转url则获取后存入redis
                        var inputData = new CardMemberCardActivateInputDto()
                        {
                            AppId = appId,
                            CardId = memberCardId,
                            OuterString = "mb"
                        };
                        
                        try
                        {
                            //获取跳转的连接
                            var retData = await _memberServices.GetCardMemberCardActivateAsync(inputData);
                            if (retData.Item1 == null)
                                msgText.Content = "欢迎关注";
                            else
                            {
                                var retUrl = retData.Item1.Url;
                                //根据回复的关键字返回内容
                                msgText.Content = $"欢迎关注，请<a href='{retUrl}'>领取会员卡</a>";
                                //存redis
                                var memberCardActiveData = new WechatMemberCardActiveDto()
                                {
                                    AppId = appId,
                                    CardId=memberCardId,
                                    JpUrl= retUrl
                                };
                                await SetMemberCardActiveObject(memberCardActiveData);
                            }
                        }
                        catch (Exception e)
                        {
                            _logger.LogError("回调获取开卡插件参数失败！"+e.Message);
                        }

                    }
                    else
                    {
                        //根据回复的关键字返回内容
                        msgText.Content = $"欢迎关注，请<a href='{jpUrl}'>领取会员卡</a>";
                    }
                    ////根据回复的关键字返回内容
                    //msgText.Content = "欢迎关注，请<a href='https://mp.weixin.qq.com/bizmall/activatemembercard?action=preshow&&encrypt_card_id=b0dKpA6h0EZbB%2BcvlSu2aALN1An%2FaLrLAGzCSZ2Gm538VHgM5dpWaxkL8AlSkKw%2B&outer_str=1ng&biz=MzkwNDIwNjY3NA%3D%3D#wechat_redirect'>领取会员卡</a>";
                }
                else
                {
                    //没有会员卡Id不回复注册链接
                    msgText.Content = "欢迎关注!";
                }
            }
            else
            {
                //存在则直接回复欢迎字样
                //根据回复的关键字返回内容
                msgText.Content = "您好！欢迎关注";
            }
            //返回微信消息xml格式
            resXml = XmlEntityExchange<ResponseMessageText>.ConvertEntity2Xml(msgText);
            return resXml;
        }
        #endregion 关键字回复

        #region 获取会员卡跳转信息
        /// <summary>
        /// 获取会员卡跳转信息
        /// </summary>
        /// <param name="appId"></param>
        /// <param name="cardId"></param>
        /// <returns></returns>
        private async Task<WechatMemberCardActiveDto> GetMemberCardActive(string appId, string cardId)
        {
            var keyWechatCard = CreateWeChatCardKey(appId, cardId);
            //获取redis里面键对应的值
            var keyWechatValue = await _redis.StringGetAsync(keyWechatCard);
            //转成对象
            var wechatMemberCard = keyWechatValue.IsNullOrEmpty ? null : UtilsHelper.DeserializeObject<WechatMemberCardActiveDto>(keyWechatValue.ToString());
            return wechatMemberCard;
        }
        #endregion

        #region 设置会员卡跳转信息
        /// <summary>
        /// 设置会员卡跳转信息
        /// </summary>
        /// <param name="wechatMemberCardActiveObject"></param>
        /// <returns></returns>
        private async Task SetMemberCardActiveObject(WechatMemberCardActiveDto wechatMemberCardActiveObject)
        {
            var keyWechat = CreateWeChatCardKey(wechatMemberCardActiveObject.AppId, wechatMemberCardActiveObject.CardId);
            var valueRet = UtilsHelper.SerializeObject<WechatMemberCardActiveDto>(wechatMemberCardActiveObject);
            await _redis.StringSetAsync(key: keyWechat, value: valueRet);
        }
        #endregion

        #region 生成key
        /// <summary>
        /// 生成key
        /// </summary>
        /// <param name="appId"></param>
        /// <param name="cardId"></param>
        /// <returns></returns>
        private string CreateWeChatCardKey(string appId, string cardId)
        {
            var keyWechatCard = $"{ConstOptions.KeyWechatCardRedisPrefix}{appId}.{cardId}";
            return keyWechatCard;
        }
        #endregion

        #endregion
    }
}
